﻿using Examine;
using Examine.Providers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Security;
using System.Web.UI.WebControls;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.propertytype;
using umbraco.DataLayer;
using umbraco.presentation;

namespace BP.Umb.Logic
{
    public class MemberUtils
    {
        protected static void PopulateMemberFromReader(MemberUtils.VisualMember m, IRecordsReader dr)
        {
            m.Id = Convert.ToString(dr.GetInt("nodeId"));
            m.Name = dr.GetString("Name");
            if (!dr.IsNull("email"))
                m.Email = dr.GetString("email");
            m.LoginName = dr.GetString("loginName");
        }

        public static List<MemberUtils.VisualMember> GetMembersByGroup(List<string> groupList, string provider, bool reverseFilter)
        {
            List<MemberUtils.VisualMember> results = new List<MemberUtils.VisualMember>();
            if (Member.InUmbracoMemberMode() && provider == "umbraconative")
            {
                if (groupList.Count == 0)
                {
                    foreach (Member member in Member.GetAll)
                        results.Add(new MemberUtils.VisualMember()
                        {
                            Id = Convert.ToString(((CMSNode)member).Id),
                            Email = member.Email,
                            LoginName = member.LoginName,
                            Name = ((CMSNode)member).Text
                        });
                }
                else if (reverseFilter)
                    Enumerable.ToList<Member>(Enumerable.Except<Member>(Member.GetAllAsList(), Enumerable.Distinct<Member>((IEnumerable<Member>)Queryable.Aggregate<Member[]>(Queryable.Select<string, Member[]>(Queryable.AsQueryable<string>((IEnumerable<string>)groupList), (Expression<Func<string, Member[]>>)(groupName => MemberGroup.GetByName(groupName).GetMembers())), (Expression<Func<Member[], Member[], Member[]>>)((a, b) => Enumerable.ToArray<Member>(Enumerable.Union<Member>(a, b))))))).ForEach((Action<Member>)(member => results.Add(new MemberUtils.VisualMember()
                    {
                        Id = Convert.ToString(((CMSNode)member).Id),
                        Email = member.Email,
                        LoginName = member.LoginName,
                        Name = ((CMSNode)member).Text
                    })));
                else
                    Enumerable.ToList<Member>(Enumerable.Distinct<Member>((IEnumerable<Member>)Queryable.Aggregate<Member[]>(Queryable.Select<string, Member[]>(Queryable.AsQueryable<string>((IEnumerable<string>)groupList), (Expression<Func<string, Member[]>>)(groupName => MemberGroup.GetByName(groupName).GetMembers())), (Expression<Func<Member[], Member[], Member[]>>)((a, b) => Enumerable.ToArray<Member>(Enumerable.Union<Member>(a, b)))))).ForEach((Action<Member>)(member => results.Add(new MemberUtils.VisualMember()
                    {
                        Id = Convert.ToString(((CMSNode)member).Id),
                        Email = member.Email,
                        LoginName = member.LoginName,
                        Name = ((CMSNode)member).Text
                    })));
            }
            else if (groupList.Count == 0)
                Enumerable.ToList<MembershipUser>(Enumerable.Select<string, MembershipUser>((IEnumerable<string>)groupList, (Func<string, MembershipUser>)(user => Membership.GetUser(user)))).ForEach((Action<MembershipUser>)(user => results.Add(new MemberUtils.VisualMember()
                {
                    Id = user.UserName,
                    Email = user.Email,
                    LoginName = user.UserName,
                    Name = user.UserName
                })));
            else if (reverseFilter)
                Enumerable.ToList<MembershipUser>(Enumerable.Except<MembershipUser>(Enumerable.OfType<MembershipUser>((IEnumerable)Membership.GetAllUsers()), Enumerable.OfType<MembershipUser>((IEnumerable)Enumerable.Select<string, MembershipUser>(Enumerable.Distinct<string>((IEnumerable<string>)Enumerable.Aggregate<string[]>(Enumerable.Select<string, string[]>((IEnumerable<string>)groupList, (Func<string, string[]>)(role => Roles.GetUsersInRole(role))), (Func<string[], string[], string[]>)((a, b) => Enumerable.ToArray<string>(Enumerable.Union<string>((IEnumerable<string>)a, (IEnumerable<string>)b))))), (Func<string, MembershipUser>)(user => Membership.GetUser(user)))))).ForEach((Action<MembershipUser>)(user => results.Add(new MemberUtils.VisualMember()
                {
                    Id = user.UserName,
                    Email = user.Email,
                    LoginName = user.UserName,
                    Name = user.UserName
                })));
            else
                Enumerable.ToList<MembershipUser>(Enumerable.Select<string, MembershipUser>(Enumerable.Distinct<string>((IEnumerable<string>)Enumerable.Aggregate<string[]>(Enumerable.Select<string, string[]>((IEnumerable<string>)groupList, (Func<string, string[]>)(role => Roles.GetUsersInRole(role))), (Func<string[], string[], string[]>)((a, b) => Enumerable.ToArray<string>(Enumerable.Union<string>((IEnumerable<string>)a, (IEnumerable<string>)b))))), (Func<string, MembershipUser>)(user => Membership.GetUser(user)))).ForEach((Action<MembershipUser>)(user => results.Add(new MemberUtils.VisualMember()
                {
                    Id = user.UserName,
                    Email = user.Email,
                    LoginName = user.UserName,
                    Name = user.UserName
                })));
            return results;
        }

        public static List<MemberUtils.VisualMember> GetMembersBySearch(string query, string provider, MemberUtils.SearchFieldType sft, MemberType mt, PropertyType pt)
        {
            IEnumerable<MemberUtils.VisualMember> source = (IEnumerable<MemberUtils.VisualMember>)new List<MemberUtils.VisualMember>();
            if (Member.InUmbracoMemberMode() && provider == "examine")
            {
                query = query.ToLower();
                BaseSearchProvider memberSearchProvider = UmbracoContext.Current.InternalMemberSearchProvider;
                if (!string.IsNullOrEmpty(query))
                    source = Enumerable.Select<SearchResult, MemberUtils.VisualMember>((IEnumerable<SearchResult>)memberSearchProvider.Search(query, false), (Func<SearchResult, MemberUtils.VisualMember>)(x => new MemberUtils.VisualMember()
                    {
                        Id = x.Fields["id"],
                        Name = x.Fields["nodeName"],
                        Email = x.Fields["email"],
                        LoginName = x.Fields["loginName"]
                    }));
            }
            else if (Member.InUmbracoMemberMode() && provider == "umbraconative")
            {
                string str1 = "";
                if (sft != MemberUtils.SearchFieldType.Custom)
                {
                    str1 = "select distinct nodeId, umbracoNode.text AS Name, cmsMember.email, cmsMember.loginName from umbracoNode INNER JOIN cmsMember ON umbracoNode.id = cmsMember.nodeId where ";
                    if (sft == MemberUtils.SearchFieldType.Email)
                        str1 = str1 + "cmsMember.email like '%" + query + "%'";
                    else if (sft == MemberUtils.SearchFieldType.Name)
                        str1 = str1 + "umbracoNode.text like '%" + query + "%'";
                }
                else if (pt != null)
                {
                    string str2;
                    string str3;
                    string str4;
                    string str5;
                    if (((CMSNode)pt.DataTypeDefinition).Id == -51)
                    {
                        str2 = "dataInt";
                        str3 = "=";
                        str4 = "";
                        str5 = "";
                    }
                    else
                    {
                        str2 = "dataNvarchar";
                        str3 = "like";
                        str4 = "'%";
                        str5 = "%'";
                    }
                    str1 = "\r\n                        SELECT       umbracoNode.id AS nodeID, umbracoNode.text AS Name, cmsMember.Email, cmsMember.LoginName\r\n                        FROM         cmsPropertyData INNER JOIN\r\n                                                    cmsPropertyType ON cmsPropertyData.propertytypeid = cmsPropertyType.id INNER JOIN\r\n                                                    umbracoNode ON cmsPropertyData.contentNodeId = umbracoNode.id INNER JOIN\r\n                                                    cmsMember ON umbracoNode.id = cmsMember.nodeId\r\n                        WHERE        (cmsPropertyType.contentTypeId = " + (object)((CMSNode)mt).Id + ") AND \r\n                                     (cmsPropertyData.propertytypeid = " + (string)(object)pt.Id + ") AND \r\n                                     (cmsPropertyData." + str2 + " " + str3 + " " + str4 + query + str5 + ")";
                }
                if (str1 != "")
                {
                    using (IRecordsReader dr = Application.SqlHelper.ExecuteReader(str1, new IParameter[0]))
                    {
                        while (dr.Read())
                        {
                            MemberUtils.VisualMember m = new MemberUtils.VisualMember();
                            MemberUtils.PopulateMemberFromReader(m, dr);
                            ((List<MemberUtils.VisualMember>)source).Add(m);
                        }
                        dr.Close();
                    }
                }
            }
            else if (sft == MemberUtils.SearchFieldType.Email)
                source = Enumerable.Select<MembershipUser, MemberUtils.VisualMember>(Enumerable.Cast<MembershipUser>((IEnumerable)Membership.FindUsersByEmail(query)), (Func<MembershipUser, MemberUtils.VisualMember>)(x => new MemberUtils.VisualMember()
                {
                    Id = x.UserName,
                    Email = x.Email,
                    LoginName = x.UserName,
                    Name = x.UserName
                }));
            else if (sft == MemberUtils.SearchFieldType.Name)
                source = Enumerable.Select<MembershipUser, MemberUtils.VisualMember>(Enumerable.Cast<MembershipUser>((IEnumerable)Membership.FindUsersByName(query + "%")), (Func<MembershipUser, MemberUtils.VisualMember>)(x => new MemberUtils.VisualMember()
                {
                    Id = x.UserName,
                    Email = x.Email,
                    LoginName = x.UserName,
                    Name = x.UserName
                }));
            return Enumerable.ToList<MemberUtils.VisualMember>(source);
        }

        public static string ConcatArray(string[] array, string delim)
        {
            string str1 = "";
            bool flag = true;
            foreach (string str2 in array)
                str1 = str1 + (flag ? "" : delim) + str2;
            return str1;
        }

        public static string DeleteMembers(List<MemberUtils.VisualMember> members)
        {
            string str = "";
            foreach (MemberUtils.VisualMember visualMember in members)
            {
                try
                {
                    Membership.GetUser(visualMember.LoginName);
                    str = !Membership.DeleteUser(visualMember.LoginName, true) ? str + visualMember.LoginName + " <i>failed</i><br/>" : str + visualMember.LoginName + " <i>deleted</i><br/>";
                }
                catch
                {
                    str = str + visualMember.LoginName + " <i>raised exception for Member '</i><br/>" + visualMember.LoginName + "'";
                }
            }
            return str;
        }

        public static string RegroupMembers(List<MemberUtils.VisualMember> memberList, string[] groupAdd, string[] groupRemove)
        {
            string[] strArray = new string[memberList.Count];
            int index = 0;
            foreach (MemberUtils.VisualMember visualMember in memberList)
            {
                strArray[index] = visualMember.LoginName;
                ++index;
            }
            try
            {
                if (groupRemove.Length > 0)
                    Roles.RemoveUsersFromRoles(strArray, groupRemove);
                if (groupAdd.Length > 0)
                    Roles.AddUsersToRoles(strArray, groupAdd);
                return "Regroup completed";
            }
            catch
            {
                return "<b>Failed to remove/add member groups</b>" + (object)strArray.Length + ", " + (string)(object)groupRemove.Length + ", " + (string)(object)groupAdd.Length + "<br/>  Members:" + MemberUtils.ConcatArray(strArray, ", ") + "<br/>  Add:" + MemberUtils.ConcatArray(groupAdd, ", ") + "<br/>  Remove:" + MemberUtils.ConcatArray(groupRemove, ", ");
            }
        }

        public static void BindSearchFields(ListItemCollection col)
        {
        }

        public enum SearchFieldType
        {
            Name,
            Email,
            Custom,
        }

        public class VisualMember
        {
            public string Id { get; set; }

            public string LoginName { get; set; }

            public string Name { get; set; }

            public string Email { get; set; }

            public VisualMember()
            {
            }

            public VisualMember(string id, string name)
            {
                this.Id = id;
                this.Name = name;
            }
        }
    }
}
